/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.tabbar;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.PageSlider;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;

import com.xuexiang.xui_lib.util.AttrValue;
import com.xuexiang.xui_lib.util.DisplayUtils;
import com.xuexiang.xui_lib.util.Log;

/**
 * 简单指示器
 *
 * @since 2021-04-15
 */
public class EasyIndicator extends DirectionalLayout implements Component.ClickedListener {
    private static final String TAG = "EasyIndicator";
    private static final int DEF_COLOR = 0xFF289CE0;
    private static final int DEF_INDICATOR_HEIGHT = 45;
    private static final int DEF_INDICATOR_LINE_HEIGHT = 3;
    private static final int DEF_INDICATOR_TEXT_SIZE = 48;
    private static final int DEF_SIZE = -1;
    private static final int DURATION_TIME = 100;
    /**
     * 选项卡点击监听
     */
    private OnTabClickListener mOnTabClickListener;
    private int screenWidth;
    private Component mIndicator;
    private PageSlider mPageSlider;
    private DirectionalLayout tabContent;
    /**
     * Tab集合
     */
    private Text[] tvs;
    /**
     * 当前显示的页卡编号
     */
    private int mCurrIndex;
    /**
     * tab默认高度
     */
    private int indicatorHeight;
    /**
     * tab宽度,默认填充全屏
     */
    private int indicatorWidth = ComponentContainer.LayoutConfig.MATCH_PARENT;
    /**
     * 是否显示指示器
     */
    private boolean isIndicatorLineShow = true;
    /**
     * 指示器默认高度
     */
    private int indicatorLineHeight;
    /**
     * 指示器颜色
     */
    private int indicatorLineColor;
    /**
     * 指示器底部线条高度
     */
    private int indicatorBottomLineHeight = 0;
    /**
     * 指示器底部线条颜色
     */
    private int indicatorBottomLineColor;

    /**
     * 中间分割线宽度
     */
    private int verticalLineW = 0;
    /**
     * 中间分割线高度
     */
    private int verticalLineH = 0;
    /**
     * 中间分割线颜色
     */
    private int verticalLineColor = DEF_COLOR;
    /**
     * 选中颜色和默认颜色
     */
    private Color indicatorSelectedColor = new Color(DEF_COLOR);
    private Color indicatorNormalColor = Color.BLACK;
    /**
     * 默认字体大小
     */
    private int indicatorTextSize;
    /**
     * 选中字体大小
     */
    private int indicatorSelectTextSize;

    private AnimatorValue mAnimatorValue;

    /**
     * 构造方法
     *
     * @param context
     */
    public EasyIndicator(Context context) {
        this(context, null);
    }

    /**
     * 构造方法
     *
     * @param context
     * @param attrSet
     */
    public EasyIndicator(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    /**
     * 构造方法
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public EasyIndicator(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(attrSet);
    }

    private void init(AttrSet attrSet) {
        setOrientation(VERTICAL);
        screenWidth = DisplayUtils.getAttributesWidth(getContext());
        initAttrSet(attrSet);

        tabContent = new DirectionalLayout(getContext());
        tabContent.setWidth(indicatorWidth);
        tabContent.setHeight(ComponentContainer.LayoutConfig.MATCH_CONTENT);
        tabContent.setOrientation(Component.HORIZONTAL);

        ShapeElement backgroundDrawable = new ShapeElement();
        backgroundDrawable.setRgbColor(RgbColor.fromArgbInt(Color.WHITE.getValue()));
        tabContent.setBackground(backgroundDrawable);

        setArrangeListener(new ArrangeListener() {
            @Override
            public boolean onArrange(int i, int i1, int i2, int i3) {
                int width = DisplayUtils.getAttributesWidth(getContext());
                if (width != screenWidth) {
                    screenWidth = width;
                    createTabIndicator();
                }
                return false;
            }
        });
    }

    private void initAttrSet(AttrSet attrSet) {
        if (attrSet != null) {
            indicatorHeight = AttrValue.getDimension(attrSet, "indicator_height", DEF_INDICATOR_HEIGHT);
            indicatorLineHeight = AttrValue.getDimension(attrSet, "indicator_line_height", DEF_INDICATOR_LINE_HEIGHT);
            indicatorBottomLineHeight = AttrValue.getDimension(attrSet, "indicator_bottom_line_height", 0);
            indicatorBottomLineColor = AttrValue.get(attrSet, "indicator_bottom_line_color", DEF_COLOR);
            indicatorSelectedColor = AttrValue.get(attrSet, "indicator_selected_color", indicatorSelectedColor);
            indicatorNormalColor = AttrValue.get(attrSet, "indicator_normal_color", indicatorNormalColor);
            indicatorLineColor = AttrValue.get(attrSet, "indicator_line_color", DEF_COLOR);
            indicatorTextSize = AttrValue.getDimension(attrSet, "indicator_textSize", DEF_INDICATOR_TEXT_SIZE);
            isIndicatorLineShow = AttrValue.get(attrSet, "indicator_line_show", isIndicatorLineShow);
            verticalLineW = AttrValue.getDimension(attrSet, "indicator_vertical_line_w", verticalLineW);
            verticalLineColor = AttrValue.get(attrSet, "indicator_vertical_line_color", verticalLineColor);
            verticalLineH = AttrValue.getDimension(attrSet, "indicator_vertical_line_h", verticalLineH);
            indicatorWidth = AttrValue.getDimension(attrSet, "indicator_width", indicatorWidth);
            indicatorSelectTextSize = AttrValue.getDimension(attrSet, "indicator_select_textSize", indicatorTextSize);

            if (indicatorWidth == 0) {
                indicatorWidth = DEF_SIZE;
            }
        }
    }

    /**
     * 外部设置PageSlider自定义
     *
     * @param viewPage
     */
    public void setPageSlider(PageSlider viewPage) {
        mPageSlider = viewPage;
        mPageSlider.addPageChangedListener(new PageSlider.PageChangedListener() {
            @Override
            public void onPageSliding(int itemPos, float itemPosOffset, int itemPosPixles) {
                // http://192.168.64.147:8099/3rd-library-team/harmony_wiki/-/issues/141;
            }

            @Override
            public void onPageSlideStateChanged(int state) {
                Log.d(TAG, "onPageSlideStateChanged %d", state);
                int page = mPageSlider.getCurrentPage();
                Log.d(TAG, "page %d", page);
            }

            @Override
            public void onPageChosen(int itemPos) {
                Log.i(TAG, "onPageChosen %d", itemPos);
                mCurrIndex = itemPos;
                setSelectorColor(tvs[itemPos]);

                setIndicator(itemPos);
            }
        });
    }

    private void setIndicator(int itemPos) {
        ComponentContainer.LayoutConfig layoutConfig = mIndicator.getLayoutConfig();
        int start = (getIndicatorWidth() + verticalLineW) * itemPos; // 起始值
        layoutConfig.setMarginLeft(start);
        mIndicator.setLayoutConfig(layoutConfig);
    }

    /**
     * 设置tab item
     *
     * @param tabTitles
     */
    public void setTabTitles(String[] tabTitles) {
        // Create tab
        tvs = new Text[tabTitles.length];
        tabContent.removeAllComponents();

        for (int index = 0; index < tabTitles.length; index++) {
            Text view = new Text(getContext());
            view.setTag(index);
            view.setText(tabTitles[index]);

            // 为组件添加对应布局的布局属性
            DirectionalLayout.LayoutConfig layoutConfig =
                new DirectionalLayout.LayoutConfig(0, indicatorHeight, LayoutAlignment.CENTER, 1);
            view.setTextAlignment(TextAlignment.CENTER);
            view.setLayoutConfig(layoutConfig);
            switch (index) {
                case 0:
                    view.setTextColor(indicatorSelectedColor);
                    view.setTextSize(indicatorSelectTextSize, Text.TextSizeType.PX);
                    Log.d(TAG, "setTabTitles indicator_select_textSize: %d", indicatorSelectTextSize);
                    break;
                default:
                    view.setTextColor(indicatorNormalColor);
                    view.setTextSize(indicatorTextSize, Text.TextSizeType.PX);
                    Log.d(TAG, "setTabTitles indicator_select_textSize: %d", indicatorTextSize);

                    break;
            }
            view.setClickedListener(this);
            tvs[index] = view;

            tabContent.addComponent(view);
            if (index != tabTitles.length - 1) {
                Component line = new Component(getContext());
                ShapeElement mBackgroundDrawable = new ShapeElement();
                mBackgroundDrawable.setRgbColor(RgbColor.fromArgbInt(verticalLineColor));
                line.setBackground(mBackgroundDrawable);
                DirectionalLayout.LayoutConfig lineConfig =
                    new DirectionalLayout.LayoutConfig(verticalLineW, verticalLineH);
                line.setLayoutConfig(lineConfig);
                tabContent.addComponent(line);
            }
        }
        removeAllComponents();
        addComponent(tabContent);

        // Create tab mIndicator
        createTabIndicator();

        // Create tab bottom line
        Component line = new Component(getContext());
        DirectionalLayout.LayoutConfig lineConfig =
            new DirectionalLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, indicatorBottomLineHeight);
        line.setLayoutConfig(lineConfig);
        ShapeElement backgroundDrawable = new ShapeElement();
        backgroundDrawable.setRgbColor(RgbColor.fromArgbInt(indicatorBottomLineColor));
        line.setBackground(backgroundDrawable);
        addComponent(line);
    }

    private void createTabIndicator() {
        if (mIndicator != null) {
            removeComponent(mIndicator);
        }
        if (isIndicatorLineShow) {
            mIndicator = new Component(getContext());
            int iw = getIndicatorWidth();
            DirectionalLayout.LayoutConfig lineConfig =
                new DirectionalLayout.LayoutConfig(iw, indicatorLineHeight);
            mIndicator.setLayoutConfig(lineConfig);
            ShapeElement mBackgroundDrawable = new ShapeElement();
            mBackgroundDrawable.setRgbColor(RgbColor.fromArgbInt(indicatorLineColor));
            mIndicator.setBackground(mBackgroundDrawable);
            setIndicator(mCurrIndex);
            addComponent(mIndicator);
        }
    }

    @Override
    public void onClick(Component component) {
        Text tv = (Text) component;
        int mPosition = (int) component.getTag();
        if (mCurrIndex == mPosition) return;
        mCurrIndex = mPosition;
        if (mPageSlider != null) {
            mPageSlider.setCurrentPage(mPosition);
        } else {
            setSelectorColor(tv);
            Log.d(TAG, "onClick mPosition:%d ;isIndicatorLineShow:%s", mPosition, isIndicatorLineShow);
            if (isIndicatorLineShow) {
                if (mAnimatorValue != null) {
                    mAnimatorValue.cancel();
                }
                mAnimatorValue = buildIndicatorAnimatorTowards(tv);
                mAnimatorValue.start();
            }
        }
        if (mOnTabClickListener != null) {
            mOnTabClickListener.onTabClick(tv.getText(), mPosition);
        }
    }

    private void setSelectorColor(Text tv) {
        for (Text text : tvs) {
            text.setTextColor(indicatorNormalColor);
            text.setTextSize(indicatorTextSize, Text.TextSizeType.PX);
        }
        tv.setTextColor(indicatorSelectedColor);
        tv.setTextSize(indicatorSelectTextSize, Text.TextSizeType.PX);
    }

    private AnimatorValue buildIndicatorAnimatorTowards(Text tv) {
        int start = mIndicator.getLeft(); // 起始值
        int end = tv.getLeft(); // 目标值
        Log.d(TAG, "buildIndicatorAnimatorTowards %d to %d ", start, end);

        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(DURATION_TIME);
        animatorValue.setLoopedCount(0);
        animatorValue.setCurveType(Animator.CurveType.ACCELERATE);
        final ComponentContainer.LayoutConfig layoutConfig = mIndicator.getLayoutConfig();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                int left = start + (int) (v * (end - start));
                layoutConfig.setMarginLeft(left);
                mIndicator.setLayoutConfig(layoutConfig);
            }
        });

        return animatorValue;
    }

    private int getIndicatorWidth() {
        if (indicatorWidth == 0 || indicatorWidth == DEF_SIZE) {
            return (screenWidth - verticalLineW * (tvs.length - 1)) / tvs.length;
        }
        return indicatorWidth;
    }

    /**
     * 选项卡点击监听
     *
     * @since 2021-04-15
     */
    public interface OnTabClickListener {
        /**
         * tab点击
         *
         * @param title
         * @param position
         */
        void onTabClick(String title, int position);
    }

    /**
     * 设置选项卡点击监听
     *
     * @param onTabClickListener
     */
    public void setOnTabClickListener(OnTabClickListener onTabClickListener) {
        mOnTabClickListener = onTabClickListener;
    }
}
